iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0

因為接下來要把開房間和遊戲的程式碼組合在一起,所以先回頭把 D21 的範例程式碼整理成 module,同時加了一些微調,方便之後做測試。

程式碼

import random

def init_game():
  # 初始玩家生命值
  initial_health = 15

  # 初始卡牌堆
  player1_deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  player2_deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  player1_hand = [player1_deck.pop(random.randint(0, len(player1_deck) - 1))]
  player2_hand = [player2_deck.pop(random.randint(0, len(player2_deck) - 1))]

  # 遊戲狀態字典
  game_state = {
    "player1_health": initial_health,
    "player2_health": initial_health,
    "player1_deck": player1_deck,
    "player2_deck": player2_deck,
    "player1_hand": player1_hand,
    "player2_hand": player2_hand,
    "current_player": 1,  # 1代表玩家1,2代表玩家2
    "winner": None  # 初始沒有獲勝者
  }
  return game_state

def draw_card(game_state):
  current_player = game_state["current_player"]
  deck = game_state[f"player{current_player}_deck"]
  hand = game_state[f"player{current_player}_hand"]

  if len(deck) > 0:
    # 從卡牌堆中隨機抽一張卡牌
    card_index = random.randint(0, len(deck) - 1)
    card_id = deck.pop(card_index)
    # 把卡牌加入手牌
    hand.append(card_id)
    print(f'玩家{current_player} 抽出 {card_id} 並加入手牌')

  # 更新遊戲狀態
  updated_state = {
    f"player{current_player}_deck": deck,
    f"player{current_player}_hand": hand,
  }
  return updated_state

# TODO 事前排除 card_id 不在玩家手牌中的案例
def play_card(game_state, card_id):
  current_player = game_state["current_player"]
  other_player = 2 if current_player == 1 else 1  # 對手
  hand = game_state[f"player{current_player}_hand"]
  other_player_health = game_state[f"player{other_player}_health"]

  if card_id in hand:
    # 找到卡牌並計算傷害值(這裡可以根據卡牌的屬性進行計算)
    damage = card_id
    # 更新對手的生命值
    other_player_health -= damage
    print(f'玩家{current_player}使用{card_id}造成傷害,玩家{other_player}生命剩下{other_player_health}點')

    if other_player_health <= 0:
      # 如果對手生命值小於等於0,遊戲結束,當前玩家獲勝
      game_state["winner"] = current_player
      print(f'遊戲結束,贏家為{current_player}')

    # 移除已經使用的卡牌
    hand.remove(card_id)
  else:
    print(f'WARN: {card_id} 不在玩家手牌中')

  # 更新遊戲狀態
  updated_state = {
    f"player{other_player}_health": other_player_health,
    f"player{current_player}_hand": hand,
    "current_player": other_player,  # 切換回合
  }
  return updated_state

def check_winner(game_state):
  return game_state["winner"]

if __name__ == "__main__":
  game_state = init_game() # 初始化遊戲
  turn = 1
  print(game_state)

  while check_winner(game_state) == None:
    current_player = game_state['current_player']
    print(f'第{turn}回合,輪到玩家{current_player},請按下 enter 表示玩家抽牌', end='')
    x = input() # 模擬玩家行動

    updated_state = draw_card(game_state)
    game_state.update(updated_state)
    print(f"玩家{current_player}的手牌:", game_state[f"player{current_player}_hand"])

    updated_state = play_card(game_state, game_state[f"player{current_player}_hand"][0])
    game_state.update(updated_state)

    print("玩家1的生命值:", game_state["player1_health"])
    print("玩家2的生命值:", game_state["player2_health"])
    turn += 1

    # print(game_state)

調整的地方

  1. 因為頁面的程式碼區塊真的很窄,所以程式碼縮排改成兩個空白字元
  2. 把原本初始化的部分包成一個 init_game()
  3. 玩家初始生命改成 15 點,為了加速遊戲測試,所以把生命值調低一點
  4. 雙方牌庫改成一樣的
  5. init_game() 會幫雙方玩家各抽一張手牌
  6. 原本測試抽牌和出牌的部分包成一個完整的 game loop,按下 enter 就會自動進行一個回合,直到其中一方玩家生命歸零為止。玩家出牌會固定出手牌第一張
  7. 加上輔助閱讀的訊息,幫助理解遊戲狀態的變化

接下來的工作幾乎都是髒活,比較難依賴 chatGPT 完成,也謝謝一路從開始看到現在的看官們,讓我們一起努力衝刺到最後,完成最終的成果吧!


上一篇
D22 來開房間吧 websocket 建立/加入房間以及開始遊戲
下一篇
D24 遊戲開始前的資料綁定
系列文
chatGPT 帶你從零開始寫 websocket 連線遊戲31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言